package cn.net.springboot.netty.learn.custom;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.util.UUID;

public class NettyLuckClient {

    public static void main(String[] args) throws InterruptedException {

        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioSocketChannel.class)
                    // .handler(new LoggingHandler(LogLevel.DEBUG))
                    .handler(new NettyLuckClientInitializer());

            // Start the connection attempt.
            Channel ch = b.connect("127.0.0.1", 8888).sync().channel();

            int version = 1;
            String sessionId = UUID.randomUUID().toString();
            String content = "I'm the luck protocol!";

            LuckHeader header = new LuckHeader(version, content.length(), sessionId);
            LuckMessage message = new LuckMessage(header, content);
            ch.writeAndFlush(message);
            ch.close();

        } finally {
            group.shutdownGracefully();
        }
    }

    static class NettyLuckClientHandler extends SimpleChannelInboundHandler<LuckMessage> {
        @Override
        protected void channelRead0(ChannelHandlerContext channelHandlerContext, LuckMessage message) throws Exception {
            System.out.println(message);
        }
    }

    static class NettyLuckClientInitializer extends ChannelInitializer<SocketChannel> {

        @Override
        protected void initChannel(SocketChannel channel) throws Exception {
            // 添加编解码器, 由于ByteToMessageDecoder的子类无法使用@Sharable注解,
            // 这里必须给每个Handler都添加一个独立的Decoder.
            channel.pipeline().addLast(new LuckEncoder());
            channel.pipeline().addLast(new LuckDecoder());

            // and then business logic.
            channel.pipeline().addLast(new NettyLuckClientHandler());

        }
    }
}